#ifndef __CMD_BUFFER_H__
#define __CMD_BUFFER_H__

#include <stdbool.h>
#include <stdint.h>

#include "RingBuffer/ring_buffer.h"

/**
 * @brief 	 指令缓冲区错误类型
 */
typedef enum _CmdBufferErrType
{
    CB_OK = 0,        // 没有问题
    CB_PARAM_ERR,     // 参数错误
    CB_LOW_PUSH_ERR,  // 底层缓冲区存入错误
    CB_INFO_PUSH_ERR, // 指令数据信息存入错误
    CB_INFO_POP_ERR,  // 指令数据信息取出错误
    CB_LOW_POP_ERR,   // 底层缓冲区取出错误
} CmdBufferErrType;

/**
 * @brief 	 指令数据信息，存放在缓存数据的头尾索引
 */
typedef struct _CmdInfo
{
    uint32_t start;
    uint32_t end;
} CmdInfo;

/**
 * @brief 	 指令处理
 */
typedef struct _CmdBuffer
{
    RingBuffer *info;     ///< 指令数据信息环形缓冲区
    RingBuffer *low;      ///< 指令数据环形缓冲区
    void (*lock)(void);   ///< 加锁
    void (*unlock)(void); ///< 解锁
} CmdBuffer;

/**
 * @fn CB_init
 * @brief 初始化指令处理对象
 * @param cb [in] 指令处理对象指针
 * @param info [in] 指令数据信息环形缓冲区对象指针
 * @param low [in] 指令数据环形缓冲区对象指针
 * @param lock [in] 加锁操作，用于数据存取的互斥操作
 * @param unlock [in] 解锁操作，用于数据存取的互斥操作
 * @return CmdBufferErrType 错误类型
 */
extern CmdBufferErrType CB_init(CmdBuffer *cb, RingBuffer *info, RingBuffer *low, void (*lock)(void), void (*unlock)(void));

/**
 * @fn CB_push
 * @brief 将指令数据存放缓冲区
 * @param cb [in] 指令处理对象指针
 * @param cmd_str [in] 传入的指令
 * @param cmd_size [in] 传入的指令长度
 * @return CmdBufferErrType 错误类型
 */
extern CmdBufferErrType CB_push(CmdBuffer *cb, const uint8_t *cmd_str, const uint32_t cmd_size);

/**
 * @fn CB_push_dma
 * @brief 使用DMA将指令数据存放缓冲区
 * @param cb [in] 指令处理对象指针
 * @param pos [in] DMA存入数据后，数据尾索引
 * @return CmdBufferErrType 错误类型
 */
extern CmdBufferErrType CB_push_dma(CmdBuffer *cb, const uint32_t pos);

/**
 * @fn CB_get_pop_cmd_size
 * @brief 获取可读取指令的数量
 * @param cb [in] 指令处理对象指针
 * @return CmdBufferErrType 错误类型
 */
extern uint32_t CB_get_pop_cmd_size(CmdBuffer *cb);

/**
 * @fn CB_pop
 * @brief 获取可读取指令的数量
 * @param cb [in] 指令处理对象指针
 * @param cmd_size [in] 需要读取的指令的长度
 * @param cmd_str [out] 读取指令存放的缓冲区，必须提供有效的指针
 * @return CmdBufferErrType 错误类型
 */
extern CmdBufferErrType CB_pop(CmdBuffer *cb, const uint32_t cmd_size, uint8_t *cmd_str);

#endif
